﻿//============================================================================
// opto_framework.hpp
// ?Copyright 2019, Opto GmbH, All rights reserved
// Include file for Opto framework C++ API
//============================================================================

#pragma once

#include "OptoFramework.h"
#include "OptoImage.h"

// C++ STL
#include <string>

// framework general/global class & types definitions
namespace Opto
{
	namespace TextAlignmentFlags
	{
		// horizontal text alignment flags
		static const unsigned short Left =  0x0001;		// align with left edge
		static const unsigned short Right = 0x0002;		// align with right edge
		static const unsigned short HCenter = 0x0004;	// centers horizontally in available space
		static const unsigned short Justify = 0x0008;	// justifies in available space
		// vertical text alignment flags
		static const unsigned short Top =  0x0020;		// align with top
		static const unsigned short Bottom = 0x0040;	// align with bottom
		static const unsigned short VCenter = 0x0080;	// centers vertically in available space
		static const unsigned short BaseLine = 0x0100;	// align with the baseline

	};  // Opto::TextAlignmentFlags  namespace


	namespace Device
	{
		enum class Type
		{
			Camera = 0,				// camera
			Light = 1,				// light
			Gpio = 2,				// general input output 
			Stage = 3,				// motorized stage
			// ...
			All = 0x0FFFFFFF,		// any type of device
			Reserved = 0x7FFFFFFF
		};

	}; // Opto::Device namespace


	namespace Attribute
	{		
		// attributes visibility
		enum class Visibility
		{
			Simple = 0,				// attribute visible if it's <= simple/beginner
			Intermediate = 1,		// attribute visible if it's <= intermediate/expert
			Advanced = 2,			// attribute visible if it's <= advanced/guru
			Favorites = 3,			// attribute visible only if belonging to 'favorites' list
			Reserved = 0x7FFFFFFF
		};

		// attributes types
		enum class Type
		{
			I32 = 0,				// attribute is a 32-bit signed integer
			I64 = 1,				// attribute is a 64-bit signed integer
			F64 = 2,				// attribute is a 64-bit float
			String = 3,				// attribute is a string		
			Enum = 4,				// attribute is an enumeration
			Bool = 5,				// attribute is a boolean
			Command = 6,			// attribute is a one push command (action)
			Path = 7,				// attribute is a path
			Register = 8,			// attribute is memory register
			Reserved = 0x7FFFFFFF
		} ;

	}; // Opto::Attribute namespace


	//============================================================================
	// Opto::Framework (10/11/2020)
	// Opto Framework class, use to initialize/exits framework libraries
	//============================================================================
	class Framework
	{
	public:
		Framework() = delete;
		~Framework() = delete;
		Framework(const Framework& other) = delete;
		Framework& operator=(const Framework& other) = delete;
		Framework(Framework&& other) = delete;
		Framework& operator=(Framework&& other) = delete;
		
		static void initialize();
		static void close();
	};


	//============================================================================
	// Opto::Exception (09/11/2020)
	// Opto Exception class
	//============================================================================
	class Exception
	{
	public:
		// constructor/destructor
		Exception();
		Exception(int code, const std::string& msg);
		~Exception();
		// copy constructor
		Exception(const Exception& e);
		// assignment operator
		Exception& operator=(const Exception& e);
		// methods
		int code() const;
		std::string description() const;
		std::string message() const;

	private:
		void _updateDescriptionFromCode(int code);
	private:
		int m_code;				// error code
		std::string m_desc;		// erorr description
		std::string m_msg;		// additional error message

	};  // Opto::Exception class



	//============================================================================
	// Opto::Point2d (09/11/2020)
	// Opto integer point 2d  class
	//============================================================================
	class Point2d
	{
	public:
		// constructors/destructor
		Point2d();
		~Point2d();
		Point2d(int x, int y);
		// copy constructor
		Point2d(const Point2d& p);
		// assignment operator
		Point2d& operator=(const Point2d& p);
		// methods
		int x() const;
		int y() const;
		void setX(int x);
		void setY(int y);

	private:
		int m_x;
		int m_y;

	}; // Opto::Point2d class


	//============================================================================
	// Opto::Point2f (09/11/2020)
	// Opto float point 2d class
	//============================================================================
	class Point2f
	{
	public:
		// constructors/destructor
		Point2f();
		~Point2f();
		Point2f(double x, double y);
		// copy constructor
		Point2f(const Point2f& p);
		// assignment operator
		Point2f& operator=(const Point2f& p);
		// methods
		double x() const;
		double y() const;
		void setX(double x);
		void setY(double y);

	private:
		double m_x;
		double m_y;

	}; // Opto::Point2f class


	//============================================================================
	// Opto::Line2d (10/11/2020)
	// Opto line 2d class
	//============================================================================
	class Line2d
	{
	public:
		// constructors/destructor
		Line2d();
		~Line2d();
		Line2d(const Point2d& start, const Point2d& end);
		// copy constructor
		Line2d(const Line2d& l);
		// assignment operator
		Line2d& operator=(const Line2d& l);
		// methods
		Point2d start() const;
		Point2d end() const;
		void setStart(const Point2d& start);
		void setEnd(const Point2d& end);

	private:
		Point2d m_start;
		Point2d m_end;

	}; // Opto::Line2d class



	//============================================================================
	// Opto::Rect2d (09/11/2020)
	// Opto rect class
	//============================================================================
	class Rect2d
	{
	public:
		Rect2d();
		Rect2d(int left, int top, int width, int height);
		~Rect2d();
		// copy constructor
		Rect2d(const Rect2d& r);
		// assignment operator
		Rect2d& operator=(const Rect2d& r);
		// methods
		int left() const;
		int top() const;
		int right() const;
		int bottom() const;
		int width() const;
		int height() const;
		Point2d topLeft() const;
		Point2d bottomRight() const;
		void setLeft(int left);
		void setTop(int top);
		void setWidth(int width);
		void setHeight(int height);
		void setTopLeft(const Point2d& tl);
		void setBottomRight(const Point2d& br);

	private:
		int m_left;
		int m_top;
		int m_width;
		int m_height;

	}; // Opto::Rect2d class



	//============================================================================
	// Opto::RotatedRect (10/11/2020)
	// Opto rotated rectangle class
	//============================================================================
	class RotatedRect
	{
	public:
		// constructors/destructor
		RotatedRect();
		~RotatedRect();
		RotatedRect(int left, int top, int width, int height, double angle);
		RotatedRect(const Point2d& topLeft, const Point2d& bottomRight, double angle);
		// copy constructor
		RotatedRect(const RotatedRect& rr);
		// assignment operator
		RotatedRect& operator=(const RotatedRect& rr);
		// methods
		// methods
		int left() const;
		int top() const;
		int width() const;
		int height() const;
		double angle() const;
		Point2d topLeft() const;
		void setLeft(int left);
		void setTop(int top);
		void setWidth(int width);
		void setHeight(int height);
		void setTopLeft(const Point2d& tl);
		void setAngle(double angle);

	private:
		int m_left;
		int m_top;
		int m_width;
		int m_height;
		double m_angle;

	}; // Opto::RotatedRect class


	//============================================================================
	// Opto::Annulus (10/11/2020)
	// Opto annulus class
	//============================================================================
	class Annulus
	{
	public:
		Annulus();
		Annulus(Point2d center, int innerRadius, int outerRadius, double startAngle, double endAngle);
		~Annulus();
		// copy constructor
		Annulus(const Annulus& a);
		// assignment operator
		Annulus& operator=(const Annulus& a);
		// methods
		Point2d center() const;
		int innerRadius() const;
		int outerRadius() const;
		double startAngle() const;
		double endAngle() const;
		void setCenter(const Point2d& center);
		void setInnerRadius(int radius);
		void setOuterRadius(int radius);
		void setStartAngle(double angle);
		void setEndAngle(double angle);
	private:
		Point2d m_center;
		int m_innerRadius;
		int m_outerRadius;
		double m_startAngle;
		double m_endAngle;

	}; // Opto::Annulus class



	//============================================================================
	// Opto::CoordinateSystem (10/11/2020)
	// Opto coordinate system class
	//============================================================================
	class CoordinateSystem
	{
	public:
		enum class XAxisDirection
		{
			LeftRight = 0,
			RightLeft = 1

		};
		enum class YAxisDirection
		{
			TopBottom = 0,
			BottomTop = 1
		};

		CoordinateSystem();
		CoordinateSystem(const Point2f& org, float angle, XAxisDirection xDir, YAxisDirection yDir);
		~CoordinateSystem();
		// copy constructor
		CoordinateSystem(const CoordinateSystem& cs);
		// assignment operator
		CoordinateSystem& operator=(const CoordinateSystem& cs);
		// methods
		void setOrigin(const Point2f& org);
		void setAngle(double angle);
		void setXDirection(XAxisDirection xdir);
		void setYDirection(YAxisDirection ydir);
		Point2f origin() const;
		double angle() const;
		XAxisDirection xDirection() const;
		YAxisDirection yDirection() const;

	private:
		Point2f m_origin;
		double m_angle;
		XAxisDirection m_xDirection;
		YAxisDirection m_yDirection;

	}; // Opto::CoordinateSystem class


	//============================================================================
	// Opto::CoordinateSystemTransform (10/11/2020)
	// Opto coordinate system transformation class
	//============================================================================
	class CoordinateSystemTransform
	{
	public:
		CoordinateSystemTransform();
		CoordinateSystemTransform(const CoordinateSystem& baseCs, const CoordinateSystem& newCs);
		~CoordinateSystemTransform();
		// copy constructor
		CoordinateSystemTransform(const CoordinateSystemTransform& cs);
		// assignment operator
		CoordinateSystemTransform& operator=(const CoordinateSystemTransform& cs);
		// methods
		void setBaseCoordinateSystem(const CoordinateSystem& baseCs);
		void setNewCoordinateSystem(const CoordinateSystem& newCs);
		CoordinateSystem baseCoordinateSystem() const;
		CoordinateSystem newCoordinateSystem() const;
	private:
		CoordinateSystem m_base;
		CoordinateSystem m_new;

	}; // Opto::CoordinateSystemTransform class



	//============================================================================
	// Opto::Rgb (09/11/2020)
	// Opto rgb class
	//============================================================================
	class Rgb
	{
	public:
		Rgb();
		Rgb(int red, int green, int blue, int alpha=255);
		~Rgb();
		// copy constructor
		Rgb(const Rgb& r);
		// assignment operator
		Rgb& operator=(const Rgb& r);
		// methods
		int red() const;
		int green() const;
		int blue() const;
		int alpha() const;
		void setRed(int r);
		void setGreen(int g);
		void setBlue(int b);
		void setAlpha(int a);
	private:
		int m_red;
		int m_green;
		int m_blue;
		int m_alpha; // 255 (non transparent), 0: (transparent)

	}; // Opto::Rgb class


	//============================================================================
	// Opto::FontOptions (09/11/2020)
	// Opto fontOptions class
	//============================================================================
	class FontOptions
	{
	public:
		FontOptions();
		FontOptions(std::string fontName, int fontSize);
		~FontOptions();
		// copy constructor
		FontOptions(const FontOptions& r);
		// assignment operator
		FontOptions& operator=(const FontOptions& r);
		// methods
		std::string name() const;
		int size() const;
		bool bold() const;
		bool italic() const;
		bool underline() const;
		bool strikeout() const;
		int horizontalFlags() const;
		int verticalFlags() const;
		double angle() const;
		void setName(const std::string& fontname);
		void setSize(int size);
		void setBold(bool bold);
		void setUnderline(bool underline);
		void setStrikeout(bool strikeout);
		void setItalic(bool italic);
		void setHorizontalFlags(int flags);
		void setVerticalFlags(int flags);
		void setAngle(double angle);

	private:
		std::string m_fontName;
		int m_fontSize;
		bool m_bold;
		bool m_italic;
		bool m_underline;
		bool m_strikeout;
		int m_horFlags;
		int m_verFlags;
		double m_angle;

	}; // Opto::FontOptions class

}; // Opto namespace